import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { showToast, showLoadingToast, closeToast } from 'vant'
import {
  getUploadSignature,
  saveFileMetadata,
  type UploadSignatureResponse,
  type SaveFileMetadataParams
} from '@/api/file'
import { useFileStore } from './file'

// 上传任务状态
export enum UploadStatus {
  WAITING = 'waiting',
  UPLOADING = 'uploading',
  SUCCESS = 'success',
  ERROR = 'error',
  CANCELED = 'canceled',
  PAUSED = 'paused'
}

export interface UploadTask {
  id: string
  file: File
  fileName: string
  fileSize: number
  parentId: number
  progress: number
  status: UploadStatus
  uploadedBytes: number
  speed: number
  remainingTime: number
  errorMessage?: string
  startTime?: number
  lastProgressTime?: number
  xhr?: XMLHttpRequest
}

export const useUploadStore = defineStore('upload', () => {
  // 状态
  const tasks = ref<UploadTask[]>([])
  const maxConcurrent = ref(3) // 最大并发上传数
  const autoRename = ref(true) // 是否自动重命名重复文件
  const maxRenameAttempts = ref(10) // 最大重命名尝试次数

  // 计算属性
  const uploadingTasks = computed(() =>
    tasks.value.filter(task => task.status === UploadStatus.UPLOADING)
  )

  const waitingTasks = computed(() =>
    tasks.value.filter(task => task.status === UploadStatus.WAITING)
  )

  const completedTasks = computed(() =>
    tasks.value.filter(task =>
      task.status === UploadStatus.SUCCESS || task.status === UploadStatus.ERROR
    )
  )

  const successTasks = computed(() =>
    tasks.value.filter(task => task.status === UploadStatus.SUCCESS)
  )

  const errorTasks = computed(() =>
    tasks.value.filter(task => task.status === UploadStatus.ERROR)
  )

  const pausedTasks = computed(() =>
    tasks.value.filter(task => task.status === UploadStatus.PAUSED)
  )

  const totalProgress = computed(() => {
    if (tasks.value.length === 0) return 0
    const totalSize = tasks.value.reduce((sum, task) => sum + task.fileSize, 0)
    const uploadedSize = tasks.value.reduce((sum, task) => sum + task.uploadedBytes, 0)
    return Math.round((uploadedSize / totalSize) * 100)
  })

  const isUploading = computed(() => uploadingTasks.value.length > 0)

  // 生成唯一ID
  const generateTaskId = () => {
    return Date.now().toString() + Math.random().toString(36).substr(2, 9)
  }

  // 生成新的文件名（处理重复文件名）
  const generateNewFileName = (originalName: string, attempt: number = 1): string => {
    const lastDotIndex = originalName.lastIndexOf('.')
    if (lastDotIndex === -1 || lastDotIndex === 0) {
      // 没有扩展名或文件名以点开头
      return `${originalName}(${attempt})`
    } else {
      // 有扩展名
      const nameWithoutExt = originalName.substring(0, lastDotIndex)
      const extension = originalName.substring(lastDotIndex)
      return `${nameWithoutExt}(${attempt})${extension}`
    }
  }

  // 检查是否是文件名冲突错误
  const checkIsFileNameConflict = (error: any): boolean => {
    if (!error) return false

    // 检查多种可能的错误格式
    const errorMessage = error.response?.data?.message || error.message || ''
    const statusCode = error.response?.status || error.code || error.status

    return (
      errorMessage === '文件名已存在' ||
      errorMessage.includes('文件名已存在') ||
      errorMessage.includes('文件名重复') ||
      errorMessage.includes('File name already exists') ||
      errorMessage.includes('duplicate') ||
      (statusCode === 500 && errorMessage.includes('文件名'))
    )
  }

  // 添加上传任务
  const addTask = (file: File, parentId: number): string => {
    const taskId = generateTaskId()
    const task: UploadTask = {
      id: taskId,
      file,
      fileName: file.name,
      fileSize: file.size,
      parentId,
      status: UploadStatus.WAITING,
      progress: 0,
      speed: 0,
      remainingTime: 0,
      uploadedBytes: 0
    }

    tasks.value.push(task)

    // 自动开始上传如果并发数允许
    startNextUpload()

    return taskId
  }

  // 批量添加上传任务
  const addUploadTasks = (files: FileList | File[], parentId: number) => {
    const fileArray = Array.from(files)
    const fileNames = new Set<string>()

    fileArray.forEach(file => {
      let fileName = file.name
      let counter = 1

      // 检查当前批次中是否有重名文件，如果有则预先重命名
      while (fileNames.has(fileName)) {
        fileName = generateNewFileName(file.name, counter)
        counter++
      }

      fileNames.add(fileName)

      // 添加任务
      const taskId = addTask(file, parentId)

      // 如果文件名被修改了，更新任务的文件名
      if (fileName !== file.name) {
        updateTask(taskId, {
          fileName,
          errorMessage: `检测到同批次文件重名，预先重命名为: ${fileName}`
        })
      }
    })
  }

  // 更新任务状态
  const updateTask = (taskId: string, updates: Partial<UploadTask>) => {
    const task = tasks.value.find(t => t.id === taskId)
    if (task) {
      Object.assign(task, updates)
    }
  }

  // 开始下一个上传任务
  const startNextUpload = async () => {
    // 检查是否达到最大并发数
    if (uploadingTasks.value.length >= maxConcurrent.value) {
      return
    }

    // 找到下一个等待的任务
    const waitingTask = waitingTasks.value[0]
    if (!waitingTask) {
      return
    }

    // 开始上传
    waitingTask.status = UploadStatus.UPLOADING
    waitingTask.startTime = Date.now()
    waitingTask.lastProgressTime = Date.now()

    try {
      await uploadFile(waitingTask)
      waitingTask.status = UploadStatus.SUCCESS
      waitingTask.progress = 100

      showToast({
        type: 'success',
        message: `${waitingTask.fileName} 上传成功`
      })

      const fileStore = useFileStore()
      await fileStore.fetchFileList()

    } catch (error) {
      waitingTask.status = UploadStatus.ERROR
      waitingTask.errorMessage = error instanceof Error ? error.message : '上传失败'

      showToast({
        type: 'fail',
        message: `${waitingTask.fileName} 上传失败`
      })
    }

    // 尝试开始下一个任务
    setTimeout(() => {
      startNextUpload()
    }, 500)
  }

  const uploadFile = async (task: UploadTask): Promise<void> => {
    const { file, fileSize, parentId } = task
    let currentFileName = task.fileName
    let attempt = 0

    // 如果不允许自动重命名，直接上传一次
    if (!autoRename.value) {
      const signature = await getUploadSignature({
        fileName: currentFileName,
        fileSize,
        contentType: file.type || 'application/octet-stream',
        parentId
      })

      await uploadToOSS(task, signature)

      await saveFileMetadata({
        fileName: currentFileName,
        fileSize,
        fileType: file.type || 'application/octet-stream',
        ossKey: signature.key,
        parentId
      })

      return
    }

    while (attempt < maxRenameAttempts.value) {
      try {
        const signature = await getUploadSignature({
          fileName: currentFileName,
          fileSize,
          contentType: file.type || 'application/octet-stream',
          parentId
        })

        await uploadToOSS(task, signature)

        await saveFileMetadata({
          fileName: currentFileName,
          fileSize,
          fileType: file.type || 'application/octet-stream',
          ossKey: signature.key,
          parentId
        })

        // 上传成功，更新任务的文件名（如果有修改）
        if (currentFileName !== task.fileName) {
          updateTask(task.id, { fileName: currentFileName })
          showToast({
            type: 'success',
            message: `文件名已存在，自动重命名为: ${currentFileName}`
          })
        }

        return // 成功完成
      } catch (error: any) {
        // 检查是否是文件名重复错误
        const isFileNameConflict = checkIsFileNameConflict(error)

        if (isFileNameConflict) {
          attempt++
          currentFileName = generateNewFileName(task.fileName, attempt)
          console.log(`文件名重复，尝试新名称: ${currentFileName}`)

          // 更新任务显示的文件名，让用户看到正在尝试的新名称
          updateTask(task.id, {
            fileName: `${currentFileName} (尝试中...)`,
            errorMessage: `文件名重复，正在尝试: ${currentFileName}`
          })

          continue // 重试
        } else {
          // 其他错误，直接抛出
          throw error
        }
      }
    }

    // 达到最大重试次数
    throw new Error(`文件名冲突，已尝试${maxRenameAttempts.value}次仍无法上传`)
  }

  const uploadToOSS = async (task: UploadTask, signature: UploadSignatureResponse): Promise<void> => {
    return new Promise((resolve, reject) => {
      const formData = new FormData()
      formData.append('key', signature.key)
      formData.append('policy', signature.policy)
      formData.append('OSSAccessKeyId', signature.accessid)
      formData.append('signature', signature.signature)
      formData.append('file', task.file)

      const xhr = new XMLHttpRequest()
      task.xhr = xhr // 存储xhr以便取消

      let lastUploadedBytes = 0

      xhr.upload.addEventListener('progress', (event) => {
        if (event.lengthComputable && task.status === UploadStatus.UPLOADING) {
          const progress = Math.round((event.loaded / event.total) * 100)
          task.progress = progress
          task.uploadedBytes = event.loaded

          const currentTime = Date.now()
          const timeDiff = currentTime - (task.lastProgressTime || task.startTime || currentTime)

          if (timeDiff > 1000) { // 每秒计算一次速度
            const bytesDiff = event.loaded - lastUploadedBytes
            task.speed = bytesDiff / (timeDiff / 1000)

            if (task.speed > 0) {
              task.remainingTime = Math.round((event.total - event.loaded) / task.speed)
            }

            task.lastProgressTime = currentTime
            lastUploadedBytes = event.loaded
          }
        }
      })

      xhr.addEventListener('load', () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve()
        } else {
          reject(new Error(`OSS上传失败: ${xhr.status}`))
        }
      })

      xhr.addEventListener('error', () => {
        reject(new Error('网络错误'))
      })

      xhr.addEventListener('timeout', () => {
        reject(new Error('上传超时'))
      })

      xhr.addEventListener('abort', () => {
        reject(new Error('上传已取消'))
      })

      xhr.timeout = 5 * 60 * 1000

      xhr.open('POST', signature.host)
      xhr.send(formData)
    })
  }


  // 暂停任务
  const pauseTask = (taskId: string) => {
    const task = tasks.value.find(t => t.id === taskId)
    if (task && task.status === UploadStatus.UPLOADING) {
      task.status = UploadStatus.PAUSED
      if (task.xhr) {
        task.xhr.abort()
      }
    }
  }

  // 恢复任务
  const resumeTask = (taskId: string) => {
    const task = tasks.value.find(t => t.id === taskId)
    if (task && task.status === UploadStatus.PAUSED) {
      task.status = UploadStatus.WAITING
      task.progress = 0
      task.uploadedBytes = 0
      startNextUpload()
    }
  }

  // 取消任务
  const cancelTask = (taskId: string) => {
    const task = tasks.value.find(t => t.id === taskId)
    if (task) {
      if (task.xhr && task.status === UploadStatus.UPLOADING) {
        task.xhr.abort()
      }
      task.status = UploadStatus.CANCELED
    }
  }

  // 移除任务
  const removeTask = (taskId: string) => {
    const index = tasks.value.findIndex(t => t.id === taskId)
    if (index > -1) {
      const task = tasks.value[index]
      if (task && task.xhr && task.status === UploadStatus.UPLOADING) {
        task.xhr.abort()
      }
      tasks.value.splice(index, 1)
    }
  }

  // 重试任务
  const retryTask = (taskId: string) => {
    const task = tasks.value.find(t => t.id === taskId)
    if (task && task.status === UploadStatus.ERROR) {
      task.status = UploadStatus.WAITING
      task.progress = 0
      task.uploadedBytes = 0
      task.errorMessage = undefined
      startNextUpload()
    }
  }

  // 清理已完成任务
  const clearCompletedTasks = () => {
    tasks.value = tasks.value.filter(
      task => task.status !== UploadStatus.SUCCESS && task.status !== UploadStatus.ERROR
    )
  }

  // 清理所有任务
  const clearAllTasks = () => {
    // 取消所有正在上传的任务
    tasks.value.forEach(task => {
      if (task.xhr && task.status === UploadStatus.UPLOADING) {
        task.xhr.abort()
      }
    })
    tasks.value = []
  }

  // 暂停所有上传
  const pauseAll = () => {
    uploadingTasks.value.forEach(task => {
      pauseTask(task.id)
    })
  }

  // 恢复所有暂停的任务
  const resumeAll = () => {
    pausedTasks.value.forEach(task => {
      resumeTask(task.id)
    })
  }

  const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 B'

    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))

    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
  }

  const formatSpeed = (bytesPerSecond: number): string => {
    return formatFileSize(bytesPerSecond) + '/s'
  }

  const formatTimeRemaining = (seconds: number): string => {
    if (seconds < 60) return `${seconds}秒`
    if (seconds < 3600) return `${Math.floor(seconds / 60)}分钟`
    return `${Math.floor(seconds / 3600)}小时${Math.floor((seconds % 3600) / 60)}分钟`
  }

  return {
    // 状态
    tasks,
    uploadingTasks,
    waitingTasks,
    completedTasks,
    successTasks,
    errorTasks,
    pausedTasks,
    totalProgress,
    isUploading,
    maxConcurrent,
    autoRename,
    maxRenameAttempts,

    // 方法
    addTask,
    addUploadTasks,
    updateTask,
    pauseTask,
    resumeTask,
    cancelTask,
    removeTask,
    retryTask,
    clearCompletedTasks,
    clearAllTasks,
    pauseAll,
    resumeAll,
    formatFileSize,
    formatSpeed,
    formatTimeRemaining
  }
})